**
** A matrix of general objects.
** How many of the operations make sense? Is this needed?
** Transpose and matrix operations on strings can be handy.
** Also nice for just arbitrary DB-like tables.
**
internal class ObjMat: Mat {

	**
	** Shape to Mat or 'Obj'?
	**
	static Mat dupOrGen(Type of, Int[] shape, Obj?[] values) {
		if (of == values.of) {
			return makeDup(shape, values)
		} else {
			// Can't just dup the list. Need to create a new one with the right 'of'.
			i := 0
			return makeGen(of, shape) {
				values[i++]
			}
		}
	}

	override Obj? get(Obj coords) {
		values[index(coords)]
	}

	**
	** TODO Allow (or require) Mats for shape and for coords.
	**
	new makeGen(Type of, Int[] shape, |Int[] coords -> Obj?| generator) {
		// TODO Delete this echo once typing is resolved!!!
		// TODO There was supposedly a fix for this. I need to look into it!!
		echo("ObjMat.makeGen: $generator")
		this.shape = shape
		values = List(of, size)
		eachCoords {
			values.add(generator(it))
		}
	}

	internal new make(Obj[][] rows) {
		nrows := rows.size
		ncols := 0
		// TODO Do we support 5x0 or 0x5 or things like that?
		rows.each {
			ncols = ncols.max(it.size)
		}
		// TODO Use the makeGen method to create this.
		shape = [nrows, ncols]
		values = List(rows[0].of, size)
		rows.each |row| {
			// TODO Finalize decision on row-major vs. column-major.
			row.each |value, j| {
				values.add(value)
			}
			if (row.size < ncols) {
				(row.size ..< ncols).each {
					// TODO But we'll want null for nullables?
					values.add(values.of->defVal)
				}
			}
		}
	}

	internal new makeDup(Int[] shape, List values): this.makeWith(shape, values.dup) {}

	**
	** Don't expose outside pod!!! It trusts the passed-in list.
	**
	** Use only for DSL or other controlled cases. Well, I guess that means we have to expose it, then.
	**
	internal new makeWith(Int[] shape, List values) {
		this.shape = shape
		if (size != values.size) {
			throw Err("bad shape $shape for list size ${values.size}")
		}
		this.values = values
	}

	override Type of() {
		values.of
	}

	override Int[] shape {
		private set {
			// We always want a fixed shape.
			// Even if we support reshape later, either make new Mats or update the shape field.
			// Making this immutable allows avoiding cloning it on exposure.
			*shape = val.toImmutable
		}
	}

	private Obj[] values

}
